Chapter 20

JavaScript in Internet Applications

by Bill Anderson


CONTENTS

When describing the syntax of a language in the previous chapter, the snippets of JavaScript code kept the focus on the topic. The examples in this chapter illustrate in detail how JavaScript works in HTML documents. Each of the simple examples covered in this chapter focuses on a particular application of JavaScript. The examples in this chapter cover how to verify forms, work with windows, work with frames, and read cookies.

A Forms Example

Without using JavaScript to verify forms, the server side validates a form with little interaction from the user. With the event handlers provided in JavaScript, the client side performs the editing. This gives the user an immediate response to the validity of the data entered. Beyond verification, the event handlers add a means of providing more interactive forms management. Listing 20.1 illustrates the capabilities of event handlers in performing this task.


Listing 20.1. JavaScript and forms.
<HTML>

<HEAD>

<TITLE>JavaScript and Forms</TITLE>

<SCRIPT LANGUAGE="JavaScript">

<!--

var lstSex=""

function chkSex(strValue) {

   if (lstSex == "") {

      lstSex = strValue

      return true

   }

   if (lstSex != strValue) {

      if (confirm("Do you wish to change value?")) {

         lstSex = strValue

         return true

      }

      else return false

   }

   return true

}

function getSport(formObj) {

   if (formObj.hobSports.checked == 1) {

      var question = "What is your favorite sport?"

      formObj.favSport.value = prompt(question, formObj.favSport.value)

   }

}

function getPlay(formObj) {

   if (formObj.hobTheater.checked == 1) {

      var question = "What is your favorite Play?"

      formObj.favPlay.value = prompt(question, formObj.favPlay.value)

   }

}

function getBook(formObj) {

   if (formObj.hobReading.checked == 1) {

      var question = "What is your favorite book?"

      formObj.favBook.value = prompt(question, formObj.favBook.value)

   }

}

function getPlace(formObj) {

   if (formObj.hobCamping.checked == 1) {

      var question = "What is your favorite place to camp?"

      formObj.favPlace.value = prompt(question, formObj.favPlace.value)

   }

}

function chkForm(formObj) {

   if (formObj.exmpName.value == "") {

      alert("\nYour name is required.\nPlease enter and resubmit form.")

      return false

   }

   if (formObj.hobSports.checked == 0 && formObj.favSport.value != "")

      formObj.favSport.value = ""

   if (formObj.hobTheater.checked == 0 && formObj.favPlay.value != "")

      formObj.favPlay.value = ""

   if (formObj.hobReading.checked == 0 && formObj.favBook.value != "")

      formObj.favBook.value = ""

   if (formObj.hobCamping.checked == 0 && formObj.favPlace.value != "")

      formObj.favPlace.value = ""

   formObj.submit()

   return true

}

// -->

</SCRIPT>

</HEAD>

<BODY>

<H1 ALIGN="CENTER">JavaScript and Forms</H1>

<P>Instead of sending the form to the server for editing, the web page

developer has the option to edit the form using JavaScript to validate

the data before it is sent to the server. This example, shows how

JavaScript event handlers execute validation functions.</P>

<HR>

<FORM NAME="example" onSubmit="alert('\nForm submitted')">

<P>Enter your name: <INPUT TYPE="TEXT" NAME="exmpName"

   onFocus='window.status="Please enter your name"'

   onBlur='window.status=""'> (required)</P>

<P>Sex:  Male <INPUT TYPE="RADIO" NAME="exmpSex" VALUE="M"

   onClick='if (!chkSex(this.value)) exmpSex[1].checked=1'>

 Female <INPUT TYPE="RADIO" NAME="exmpSex" VALUE="F"

   onClick='if (!chkSex(this.value)) exmpSex[0].checked=1'></P>

<P>Check the boxes that match your hobbies:<BR>

<INPUT TYPE="CHECKBOX" NAME="hobSports"

   onClick='getSport(this.form)'> Sports<BR>

<INPUT TYPE="CHECKBOX" NAME="hobTheater"

   onClick='getPlay(this.form)'> Theater<BR>

<INPUT TYPE="CHECKBOX" NAME="hobReading"

   onClick='getBook(this.form)'> Reading<BR>

<INPUT TYPE="CHECKBOX" NAME="hobCamping"

   onClick='getPlace(this.form)'> Camping</P>

<INPUT TYPE="HIDDEN" NAME="favSport">

<INPUT TYPE="HIDDEN" NAME="favPlay">

<INPUT TYPE="HIDDEN" NAME="favBook">

<INPUT TYPE="HIDDEN" NAME="favPlace">

<P>Are there any special comments:<BR>

<TEXTAREA NAME="exmpCmnts" ROWS="4" COLS="40" WRAP="VIRTUAL"

   onFocus='window.status="Looking forward to your comments."'

   onBlur='window.status=""'>

</TEXTAREA></P>

<P><INPUT TYPE="SUBMIT" VALUE="Submit Form" onClick='chkForm(this.form)'>

<INPUT TYPE="RESET" VALUE="Clear Form"></P>

</FORM>

</BODY>

</HTML>


The onFocus and onBlur event handlers in the input text statement show how to display a message in the status bar. The onFocus event handler displays the message and the onBlur removes it when it is no longer applicable. Although the onBlur event handler looks like a natural candidate for validating the value of the text, it presents a serious problem in that leaving the page causes its execution. Thus, the user, who wanted to exit the page without completing the form, gets an error message. As an exercise, change the event handler to call the chkForm function and see how it behaves.

For the radio buttons, the listing illustrates a simple change test. Both buttons use the same function to determine if a change occurred. If a change occurred, the user is prompted (see Figure 20.1) to verify the change. The false output generated by cancel causes the value of checked to change. The variable checked modifies both the visual display and the value of the exmpSex variable, while the check() method only modifies the variable and not the visual display. Again, the reader can change the script to see the difference between modifying checked and using the check() method.

Figure 20.1 : Using the Confirm dialog box.

The checkbox section of the preceding listing shows how additional information can be gained and stored in a hidden form entry. The function prompts the user for information (see Figure 20.2) when the box is checked and not checked. The script retains the value of the hidden information rather than having the user re-enter the information, then uncheck and recheck the box.

Figure 20.2 : Using the Prompt dialog box.

Finally, the script's use of the onClick() alert handler for the submit button shows one alternative of validating forms submission. In this approach, the function, after it performs the validation checks, submits the form using the submit() method. In addition, the validation function takes care of cleaning up the hidden variables. The onSubmit() event handler now displays an alert (see Figure 20.3) that the script submitted the form.

Figure 20.3 : Using the Alert dialog box.

A Windows Example

While the previous example covered the windows created by the alert(), confirm(), and prompt() methods, this example looks at the behavior of the window.open() method. This self-explanatory HTML document (see Listing 20.2) shows windows open under different conditions.


Listing 20.2. JavaScript and Windows.
<HTML>

<HEAD>

<TITLE>JavaScript Windows Example</TITLE>

<SCRIPT LANGUAGE="JavaScript">

<!--

var win4Open=false

function winTest4() {

   winTst4=window.open("", "winS", "resizable,width=200,height=100")

   winTst4.document.open()

   winTst4.document.write("<H1>Test 4</H1>")

   winTst4.document.close()

   win4Open=true

}

function endIt() {

   if (win4Open) winTst4.close()

}

// -->

</SCRIPT>

</HEAD>

<BODY onUnLoad='endIt()'>

<H1 ALIGN="CENTER">A JavaScript Windows Example</H1>

<P>HTML lacks the means to create windows. Frames, yes -- windows ,

no. The best way to learn about the behavior of windows is to play

with this script.</P>

<HR>

<FORM>

<P>This window test generates a new instance of the browser,

with this document as the opening document. Close the first instance

of the browser to see what happens.<BR><BR>

<INPUT TYPE="button" NAME="test1" VALUE="Open Test 1"

   onClick='window.open("window.htm")'></P>

<HR>

<P>By declaring a named windowed object, it is still possible to

create multiple instance of the browser.<BR><BR>

<INPUT TYPE="button" NAME="test2" VALUE="Open Test 2"

   onClick='winTST2 = window.open("window.htm")'></P>

<HR>

<P>When the name argument to window.open is provided, it cannot

another copy with a duplicate name. Instead, it reopens the

same document.<BR><BR>

<INPUT TYPE="button" NAME="test3" VALUE="Open Test 3"

   onClick='winTST3 = window.open("window.htm", "winTest")'></P>

<HR>

<P>This final test shows away to use the onUnLoad option to close

any windows created. You can run test 1 or 2 and run this test

from another instance of the browser.<BR><BR>

<INPUT TYPE="button" NAME="test4" VALUE="Open Test 4"

   onClick='winTest4()'></P>

</FORM>

</BODY>

</HTML>


As the various window tests illustrate, windows are independent entities. As long as the window object has a name, it can be explicitly addressed from any other window.

NOTE
The window object name is not the same as the window name argument. The window name argument is related to the TARGET attribute in the <FORM> and <A> tags

The preceding example shows a simple method for closing windows that are open, as shown in Figure 20.4. Because the window might not be open, the script tests to see if it was opened prior to closing.

Figure 20.4 : The Test 4 results.


TIP
Unless there is a reason for doing otherwise, a good programming practice calls for the closing of all windows that are opened

A Frames Example

The HTML equivalent of opening windows is the <FRAMESET> tag, which divides the screen real estate into smaller windows. The <FRAMESET> tag replaces the <BODY> tag so that, except for the <NOFRAMES> tag, the document's sole purpose is to define a set of frames, as shown in Listing 20.3.


Listing 20.3. HTML for parent <FRAMESET>.
<HTML>

<HEAD>

<TITLE>JavaScript and Forms</TITLE></HEAD>

<FRAMESET ROWS="20%,*">

<FRAME SRC="fr_top.htm" NAME="topFrame" SCROLLING="NO">

<FRAME SRC="fr_main.htm" NAME="bigFrame">

</FRAMESET>

</HTML>


For a frame to actually appear on the screen, a document must be defined, as is done for the topFrame. As Listing 20.4 shows, this is a very minimal document.


Listing 20.4. HTML for topFrame.
<HTML>

<HEAD>

<TITLE>Top Frame Title</TITLE>

</HEAD>

<BODY>

<H1 ALIGN="CENTER">JavaScript and Frames</H1>

</BODY>

</HTML>


The document loaded into bigFrame is another <FRAMESET> document. (See Listing 20.5.) This approach makes the new <FRAMESET> a child to the first <FRAMESET>.


Listing 20.5. A child <FRAMESET>.
<HTML>

<HEAD>

<TITLE>Main Frameset</TITLE>

</HEAD>

<FRAMESET COLS="25%,*">

<FRAME SRC="fr_cntrl.htm" NAME="frameControl">

<FRAME SRC="fr_dsply.htm" NAME="frameDisplay">

</FRAMESET>

</HTML>


Other than as an example, there are advantages to this approach over the inclusion of the <FRAMESET> as an embedded <FRAMESET> with the first <FRAMESET>. By creating a child <FRAMESET>, the bigFrame is free to receive any kind of document. For example, if the topFrame contains a series of buttons describing alternate formats, the <FRAMESET> for bigFrame changes, according to the needs of the application.

Like topFrame, frameDisplay needs an initial document. For this example, the document is a short description of this example as shown in Listing 20.6.


Listing 20.6. Initial document for frameDisplay.
<HTML>

<HEAD>

<TITLE>Initial Doc for Display Frame</TITLE>

</HEAD>

<BODY>

<H1 ALIGN="CENTER">Initial Document for Test</H1>

<P>For a frame to be define, an initial document must be

opened in the frame. This is different than a window, which

allows a window to be opened with no document. In this

example, the control panel changes the document displayed in

this window.</P>

</BODY>

</HTML>


The HTML document (see Listing 20.7) loaded in frameControl shows how one document can manipulate other frames.


Listing 20.7. The Control Panel document.
<HTML>

<HEAD>

<TITLE>Control Frame</TITLE>

<SCRIPT LANGUAGE="JavaScript">

<!--

function chgHeader() {

var newhdr=prompt("Enter new title for top frame.", "")

if (newhdr.length > 0) {

     top.topFrame.document.open()

     top.topFrame.document.write('<H1 ALIGN="center">'+newhdr+"</H1>")

     top.topFrame.document.close()

  }

}

// -->

</SCRIPT>

</HEAD>

<BODY>

<H2 ALIGN="CENTER">Control</H2>

<FORM>

<INPUT TYPE="button" NAME="test1" VALUE="Load Forms"

   onClick='top.bigFrame.frameDisplay.location="forms.htm"'><BR>

<INPUT TYPE="button" NAME="test2" VALUE="Restore"

   onClick='top.bigFrame.frameDisplay.location="fr_dsply.htm"'><BR>

<INPUT TYPE="button" NAME="test3" VALUE="Change Header"

   onClick='chgHeader()'><BR>

</FORM>

</BODY>

</HTML>


Figure 20.5 shows the screen when frames.htm is loaded.

Figure 20.5 : Initial window for the Frames example.

The references used in this document illustrate the format required to address the different frames. For the first two buttons, the reference must start from the top window. It includes the references to the parent frame and child frame. The keyword top forces the reference to start from the original because the control panel is a document of the child <FRAMESET>. When the Load Forms button is clicked, the forms document described in the first example is loaded into the display frame, as shown in Figure 20.6.

Figure 20.6 : Loading the Forms example.

The Change Header button executes a function that prompts the user for a new value for the topFrame. (See Figure 20.7.) In this case, the document method opens a new document in the frame, writes the new header to it, and then closes the document.

Figure 20.7 : Changing the Header in the Top Frame.

The control frame could change the values for the colors in the other frames. It could also reference the data collected in the form's example. By using JavaScript to enhance the HTML documents, the Web page developer has a much greater degree of flexibility in designing Web documents.

Reading the Cookie File

There are times when trying to improve on the wheel is counterproductive. This is one of them. Bill Dortch's public domain routine for the management of cookies is a straightforward, well-written piece of code. Listing 20.8 is the latest release of his work.


Listing 20.8. JavaScript code for reading a cookie file.
<html>

<head>

<title>Cookie Examples</title>

</head>

<body>

<script language="javascript">

<!-- begin script

//

//  Cookie Functions - Second Helping  (21-Jan-96)

//  Written by:  Bill Dortch, hIdaho Design <bdortch@netw.com>

//  Original location:   http://hidaho.com/cookies/

//  The following functions are released to the public domain.

//

//  1.  The expires parameter is now optional - that is, you can omit

//      it instead of passing it null to expire the cookie at the end

//      of the current session.

//

//  2.  An optional path parameter has been added.

//

//  3.  An optional domain parameter has been added.

//

//  4.  An optional secure parameter has been added.

//

//  For information on the significance of these parameters, and

//  and on cookies in general, please refer to the official cookie

//  spec, at:

//

//      http://www.netscape.com/newsref/std/cookie_spec.html

//

//

// "Internal" function to return the decoded value of a cookie

//

function getCookieVal (offset) {

  var endstr = document.cookie.indexOf (";", offset);

  if (endstr == -1)

    endstr = document.cookie.length;

  return unescape(document.cookie.substring(offset, endstr));

}



//

//  Function to return the value of the cookie specified by "name".

//    name - String object containing the cookie name.

//    returns - String object containing the cookie value, or null if

//      the cookie does not exist.

//

function GetCookie (name) {

  var arg = name + "=";

  var alen = arg.length;

  var clen = document.cookie.length;

  var i = 0;

  while (i < clen) {

    var j = i + alen;

    if (document.cookie.substring(i, j) == arg)

      return getCookieVal (j);

    i = document.cookie.indexOf(" ", i) + 1;

    if (i == 0) break;

  }

  return null;

}



//

//  Function to create or update a cookie.

//    name - String object object containing the cookie name.

//    value - String object containing the cookie value.  May contain

//      any valid string characters.

//    [expires] - Date object containing the expiration data of the cookie.  If

//      omitted or null, expires the cookie at the end of the current session.

//    [path] - String object indicating the path for which the cookie is valid.

//      If omitted or null, uses the path of the calling document.

//    [domain] - String object indicating the domain for which the cookie is

//      valid.  If omitted or null, uses the domain of the calling document.

//    [secure] - Boolean (true/false) value indicating whether cookie

//      transmission requires a secure channel (HTTPS).

//

//  The first two parameters are required.  The others, if supplied, must

//  be passed in the order listed above.  To omit an unused optional field,

//  use null as a place holder.  For example, to call SetCookie using name,

//  value and path, you would code:

//

//      SetCookie ("myCookieName", "myCookieValue", null, "/");

//

//  Note that trailing omitted parameters do not require a placeholder.

//

//  To set a secure cookie for path "/myPath", that expires after the

//  current session, you might code:

//

//      SetCookie (myCookieVar, cookieValueVar, null, "/myPath", null, true);

//

function SetCookie (name, value) {

  var argv = SetCookie.arguments;

  var argc = SetCookie.arguments.length;

  var expires = (argc > 2) ? argv[2] : null;

  var path = (argc > 3) ? argv[3] : null;

  var domain = (argc > 4) ? argv[4] : null;

  var secure = (argc > 5) ? argv[5] : false;

  document.cookie = name + "=" + escape (value) +

    ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +

    ((path == null) ? "" : ("; path=" + path)) +

    ((domain == null) ? "" : ("; domain=" + domain)) +

    ((secure == true) ? "; secure" : "");

}



//  Function to delete a cookie. (Sets expiration date to current date/time)

//    name - String object containing the cookie name

//

function DeleteCookie (name) {

  var exp = new Date();

  exp.setTime (exp.getTime() - 1);  // This cookie is history

  var cval = GetCookie (name);

  document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();

}



//

//  Example

//

var expdate = new Date ()

// 24 hours from now

expdate.setTime (expdate.getTime() + (24 * 60 * 60 * 1000));

SetCookie ("FreqGrafxPath", "http://www.his.com/~smithers/freq/",

expdate,"/~smithers/freq/")

SetCookie ("coName", "Frequency Graphics", expdate)

SetCookie ("tempvar", "This is a temporary cookie.")

SetCookie ("ubiquitous", "This cookie will work anywhere in this domain",

null,"/")

SetCookie ("inBetaOnly", "This cookie will work in the ./beta/ directory",

expdate,"/~smithers/freq/beta")

SetCookie ("goner", "This cookie must die!")

document.write (document.cookie + "<br>")

DeleteCookie ("goner")

// end script -->

</script>

</body>

</html>


Resources on the Web

JavaScript is a new and evolving scripting language. The following resources help one to keep up with the changes:

The Netscape site provides other valuable resources, including a JavaScript Guide. You can access the current version of the JavaScript Guide by selecting Help | Handbook from your Netscape Navigator menu bar. There is much more, but all links can be found at the preceding sites.

Summary

This chapter covered examples for forms, windows, frames, and cookies. These are complete examples that the reader can use to explore the world of JavaScript. The sites listed in the resources section provide more examples and tutorials.